/*

 ******************************************************************************

 * [url=home.php?mod=space&uid=288409]@file[/url]    read_data_polling.c

 * [url=home.php?mod=space&uid=187600]@author[/url]  MEMS Software Solution Team

 * [url=home.php?mod=space&uid=247401]@brief[/url]   This file shows how to get data from sensor .

 *

 ******************************************************************************

 * @attention

 *

 * <h2><center>© Copyright (c) 2020 STMicroelectronics.

 * All rights reserved.</center></h2>

 *

 * This software component is licensed by ST under BSD 3-Clause license,

 * the "License"; You may not use this file except in compliance with the

 * License. You may obtain a copy of the License at:

 *                        opensource.org/licenses/BSD-3-Clause

 *

 ******************************************************************************

 */



/*

 * This example was developed using the following STMicroelectronics

 * evaluation boards:

 *

 * - STEVAL_MKI109V3 + STEVAL-MKI192V1

 * - NUCLEO_F401RE + X_NUCLEO_IKS01A3

 * - DISCOVERY_SPC584B + STEVAL-MKI192V1

 *

 * and STM32CubeMX tool with STM32CubeF4 MCU Package

 *

 * Used interfaces:

 *

 * STEVAL_MKI109V3    - Host side:   USB (Virtual COM)

 *                    - Sensor side: SPI(Default) / I2C(supported)

 *

 * NUCLEO_STM32F401RE - Host side: UART(COM) to USB bridge

 *                    - I2C(Default) / SPI(supported)

 *

 * DISCOVERY_SPC584B  - Host side: UART(COM) to USB bridge

 *                    - Sensor side: I2C(Default) / SPI(supported)

 *

 * If you need to run this example on a different hardware platform a

 * modification of the functions: `platform_write`, `platform_read`,

 * `tx_com` and 'platform_init' is required.

 *

 */



/* STMicroelectronics evaluation boards definition

 *

 * Please uncomment ONLY the evaluation boards in use.

 * If a different hardware is used please comment all

 * following target board and redefine yours.

 */



//#define STEVAL_MKI109V3  /* little endian */

//#define NUCLEO_F401RE    /* little endian */

//#define SPC584B_DIS      /* big endian */



/* ATTENTION: By default the driver is little endian. If you need switch

 *            to big endian please see "Endianness definitions" in the

 *            header file of the driver (_reg.h).

 */



/* NUCLEO_F401RE: Define communication interface */






/* Includes ------------------------------------------------------------------*/

#include <string.h>

#include <stdio.h>

#include "lps22hh_reg.h"

#include "stm32l0xx_hal.h"
#include "read_data_polling.h"

#include <stdbool.h>


extern I2C_HandleTypeDef hi2c1;

#define SENSOR_BUS hi2c1

/* Private macro -------------------------------------------------------------*/

#define BOOT_TIME    5 //ms



#define TX_BUF_DIM  1000



/* Private variables ---------------------------------------------------------*/

static uint8_t whoamI, rst;

//static uint8_t tx_buffer[TX_BUF_DIM];



lps22hh_ctx_t dev_ctx;

lps22hh_reg_t reg;



/* Extern variables ----------------------------------------------------------*/



/* Private functions ---------------------------------------------------------*/



/*

 *   WARNING:

 *   Functions declare in this section are defined at the end of this file

 *   and are strictly related to the hardware platform used.

 *

 */

static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len);

static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len);

//static void tx_com( uint8_t *tx_buffer, uint16_t len );

static void platform_delay(uint32_t ms);

static void platform_init(void);

#define AVERAGE_DATA_COUNT  3  //滤波求平均的时候，需要计算的数据总个数

static bool already_have_full_buffer = false;
static double Data_Average[AVERAGE_DATA_COUNT]={0};//存放滤波求平均的数据
static int Data_Average_Index = 0;//当前使用的是哪一个索引
double Get_Average_Raw_Data(double newData)
{
    double average = 0;
    double total = 0;
    Data_Average[Data_Average_Index++] = newData;

    if(already_have_full_buffer == true)
    {
        for(int i=0;i<AVERAGE_DATA_COUNT;i++)
        {
            total = total+Data_Average[i];
        }
        average = total/AVERAGE_DATA_COUNT;
    }
    else
    {
        for(int i=0;i<Data_Average_Index;i++)
        {
            total = total+Data_Average[i];
        }
        average = total/Data_Average_Index;
    }
    //printf("index:%d,newdata:%f,raw average:%f\n",Data_Average_Index,newData,average);

    if(Data_Average_Index >= AVERAGE_DATA_COUNT)
    {
        Data_Average_Index = 0;
        already_have_full_buffer = true;
    }
    return average;
}


void Print_Hex(unsigned char* head, unsigned char* data, unsigned char length)
{
    printf("%s:\n",head);
    for(short i=0;i<length;i++)
    {
        printf(" %02x",data[i]);
    }
    printf("\n");
}

void lps22hh_read_data_polling(void)
{
  uint8_t data_raw_pressure[3];
  //uint8_t data_raw_temperature[2];
  double pressure_hPa;
  double pressure_Pa;
  //float temperature_degC;

		/* Read samples in polling mode (no int) */
    uint8_t data[1];
		/* Read output only if new value is available */
    lps22hh_read_reg(&dev_ctx, LPS22HH_STATUS, (uint8_t *)data, 1);
    //printf("LPS22HH_STATUS:0x%x\n",data[0]);

    if ((data[0]&0x1) == 0x1 ) {
        memset(&data_raw_pressure, 0x00, sizeof(data_raw_pressure));
        lps22hh_pressure_raw_get(&dev_ctx, data_raw_pressure);
        //Print_Hex("pressure",data_raw_pressure,sizeof(data_raw_pressure));
        /*
        从以下三个寄存器中读取压力数据：PRESS_OUT_H / PRESS_OUT_L / PRESS_OUT_XL;
        如果用了传感器内部 FIFO，则读 FIFO_DATA_OUT_PRESS_H / FIFO_DATA_OUT_PRESS_L / FIFO_DATA_OUT_PRESS_XL
        */
        pressure_hPa = ((data_raw_pressure[2] << 16) + (data_raw_pressure[1] << 8) + data_raw_pressure[0])/4096.0; //lps22hh_from_lsb_to_hpa( data_raw_pressure);
        pressure_Pa = pressure_hPa * 100;
        //printf("lps22hh pressure [hPa]:%6.2f\r\n", pressure_hPa);
        //printf("lps22hh pressure [Pa]:%.2f\r\n", pressure_Pa);
        pressure_Pa = Get_Average_Raw_Data(pressure_Pa);
        printf("%.2f\r\n", pressure_Pa);
        //sprintf((char *)tx_buffer, "lps22hh pressure [hPa]:%6.2f\r\n", pressure_hPa);
        //tx_com( tx_buffer, strlen( (char const *)tx_buffer ) );
    }
#if 0
    if (reg.status.t_da) {
        memset(&data_raw_temperature, 0x00, sizeof(int16_t));
        lps22hh_temperature_raw_get(&dev_ctx, data_raw_temperature);
        Print_Hex("temperature",data_raw_temperature,sizeof(data_raw_temperature));
        /*
        从以下两个寄存器中读取压力数据：TEMP_OUT_H / TEMP_OUT_L;
        如果用了传感器内部 FIFO，则读 FIFO_DATA_OUT_TEMP_H / FIFO_DATA_OUT_TEMP_L
        */
        temperature_degC = ((data_raw_temperature[1] << 8) + data_raw_temperature[0])/100.0; //lps22hh_from_lsb_to_celsius(data_raw_temperature );
			  printf("lps22hh temperature [degC]:%6.2f\r\n", temperature_degC );
        //sprintf((char *)tx_buffer, "lps22hh temperature [degC]:%6.2f\r\n", temperature_degC );
        //tx_com( tx_buffer, strlen( (char const *)tx_buffer ) );
    }
#endif
}


void lps22hh_init( void )
{
		/* Initialize mems driver interface */

    dev_ctx.write_reg = platform_write;
    dev_ctx.read_reg = platform_read;
    //dev_ctx.mdelay = platform_delay;
    dev_ctx.handle = &SENSOR_BUS;

		/* Initialize platform specific hardware */
    platform_init();

		/* Wait sensor boot time */
    platform_delay(BOOT_TIME);

		/* Check device ID */
    whoamI = 0;
    lps22hh_device_id_get(&dev_ctx, &whoamI);
    printf("lps22hh device id is %x\n",whoamI);

    if ( whoamI != LPS22HH_ID )
    {
        while (1) /*manage here device not found */
        {
            HAL_Delay(1000);
            printf("ERR:manage here device not found\n");
        }
    }

		/* Restore default configuration */
    lps22hh_reset_set(&dev_ctx, PROPERTY_ENABLE);
    do {
    lps22hh_reset_get(&dev_ctx, &rst);

    } while (rst);

		/* Enable Block Data Update */
    lps22hh_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);

		/* Set Output Data Rate */
    lps22hh_data_rate_set(&dev_ctx, LPS22HH_75_Hz_LOW_NOISE);
    printf("lps22hh_init finished.\n");
}



/*

 * [url=home.php?mod=space&uid=247401]@brief[/url]  Write generic device register (platform dependent)

 *

 * @param  handle    customizable argument. In this examples is used in

 *                   order to select the correct sensor bus handler.

 * @param  reg       register to write

 * @param  bufp      pointer to data to write in register reg

 * @param  len       number of consecutive register to write

 *

 */

static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
    if(HAL_I2C_Mem_Write(handle, LPS22HH_I2C_ADD_H, reg,I2C_MEMADD_SIZE_8BIT, (uint8_t*) bufp, len, 1000) == HAL_OK)
    {
      return 0;
    }
    else
    {
      printf("platform_write failed\n");
      return 1;
    }
}

/*

 * @brief  Read generic device register (platform dependent)

 *

 * @param  handle    customizable argument. In this examples is used in

 *                   order to select the correct sensor bus handler.

 * @param  reg       register to read

 * @param  bufp      pointer to buffer that store the data read

 * @param  len       number of consecutive register to read

 *

 */

static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len)
{
    if(HAL_I2C_Mem_Read(handle, LPS22HH_I2C_ADD_L, reg,I2C_MEMADD_SIZE_8BIT, bufp, len, 1000)==HAL_OK)
    {
      return 0;
    }
    else
    {
      printf("platform_read failed\n");
      return 1;
    }
}

/*

 * @brief  Write generic device register (platform dependent)

 *

 * @param  tx_buffer     buffer to transmit

 * @param  len           number of byte to send

 *

 */
/*
static void tx_com(uint8_t *tx_buffer, uint16_t len)
{
    //HAL_UART_Transmit(&huart1, tx_buffer, len, 1000);
		printf("send data:\n");
    for(short i=0;i<len;i++)
    {
        printf(" %02x",tx_buffer[i]);
    }
    printf("\n");
}
*/
/*

 * @brief  platform specific delay (platform dependent)

 *

 * @param  ms        delay in ms

 *

 */

static void platform_delay(uint32_t ms)
{
    HAL_Delay(ms);
}

/*

 * @brief  platform specific initialization (platform dependent)

 */

static void platform_init(void)
{
}

